package com.shelpe.services.sinbad.service.rtr;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shelpe.services.sinbad.constant.MobileRank;
import com.shelpe.services.sinbad.constant.PCRank;
import com.shelpe.services.sinbad.controller.dto.KeywordRealtimeRank;
import com.shelpe.services.sinbad.entity.jpa.Adgroup;
import com.shelpe.services.sinbad.entity.mongo.KeywordRealtimeRankSyncLog;
import com.shelpe.services.sinbad.model.Keyword;
import com.shelpe.services.sinbad.repository.jpa.AdgroupRepository;
import com.shelpe.services.sinbad.repository.mongo.KeywordRealtimeRankSyncLogRepository;
import com.shelpe.services.sinbad.service.simbaproxy.AuthClient;
import com.shelpe.services.sinbad.service.simbaproxy.RankClient;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class RealRankingService {
	@Autowired
	private RankClient rankClient;
	@Autowired
	private KeywordRealtimeRankSyncLogRepository KeywordRealtimeRankSyncLogRepository;
	@Autowired
	private AdgroupRepository adgroupRepository;
	@Autowired
	private AuthClient authClient;

	private final String DEVICE_MOBILE = "mobile";
	private final String DEVICE_PC = "pc";
	private final String DEVICE_ALL = "all";

	public List<KeywordRealtimeRank> findRanking(List<Keyword> keywords, long adgroupID, List<Long> keywordIDs,
			Date queryTime, String device, int time) {
		List<KeywordRealtimeRank> dtos = new ArrayList<KeywordRealtimeRank>();
		List<KeywordRealtimeRankSyncLog> existings = this.KeywordRealtimeRankSyncLogRepository
				.findByAdgroupIDAndKeywordIDInAndDateGreaterThan(adgroupID, keywordIDs, queryTime);
		List<Long> existingKeywordIDs = new ArrayList<Long>();
		if (existings != null && existings.size() > 0) {
			for (KeywordRealtimeRankSyncLog existing : existings) {
				if (existingKeywordIDs.indexOf(existing.getKeywordID()) == -1) {
					existingKeywordIDs.add(existing.getKeywordID());
				}
				if (existing.getItem() != null) {
					KeywordRealtimeRank dto = new KeywordRealtimeRank();
					dto.setKeywordID(existing.getItem().getKeywordID());
					dto.setWord(existing.getItem().getWord());
					MobileRank mRank = MobileRank.from(existing.getItem().getRank().getMoibleRank());
					PCRank pcRank = PCRank.from(existing.getItem().getRank().getPcRank());
					this.from(dto, device, mRank, pcRank);
					dtos.add(dto);
				}
			}
			/** 判断是否还有关键词未获取到 **/
			if (existingKeywordIDs != null && existingKeywordIDs.size() > 0 && dtos != null && dtos.size() > 0) {
				keywordIDs.removeAll(existingKeywordIDs);
				if (keywordIDs != null && keywordIDs.size() > 0) {
					dtos.addAll(this.syncRanking(keywords, adgroupID, keywordIDs, device, time));
				}
			}
		}
		return dtos;
	}

	public List<KeywordRealtimeRank> syncRanking(List<Keyword> keywords, long adgroupID, List<Long> keywordIDs,
			String device, int time) {
		List<KeywordRealtimeRank> dtos = new ArrayList<KeywordRealtimeRank>();
		Adgroup adgroup = this.adgroupRepository.findOne(adgroupID);
		if (adgroup == null) {
			return dtos;
		}
		AuthClient.UserToken token = this.authClient.findSessionKeyByID(adgroup.getUserID());
		if (token != null && token.isExpired()) {
			return dtos;
		}
		List<RankClient.KeywordRealtimeRankItem> ranks = new ArrayList<RankClient.KeywordRealtimeRankItem>();
		List<KeywordRealtimeRankSyncLog> syncLogs = new ArrayList<KeywordRealtimeRankSyncLog>();

		while (keywordIDs.size() > 0) {
			List<Long> toFindKeywordIDs = new ArrayList<Long>();
			if (keywordIDs.size() > 20) {
				toFindKeywordIDs.addAll(keywordIDs.subList(0, 20));
				keywordIDs = keywordIDs.subList(20, keywordIDs.size());
			} else {
				toFindKeywordIDs.addAll(keywordIDs.subList(0, keywordIDs.size()));
				keywordIDs.clear();
			}
			RankClient.KeywordRealtimeRankItemResponse res = this.rankClient.findRealtimeRanks(adgroup.getNick(),
					adgroupID, toFindKeywordIDs);
			if (res != null && res.getRes() != null && res.getRes().getResult() != null
					&& res.getRes().getResult().getDataList() != null
					&& res.getRes().getResult().getDataList().getItems() != null) {
				for (RankClient.KeywordRealtimeRankItem rank : res.getRes().getResult().getDataList().getItems()) {
					log.debug("realtime rank: {}", rank);
					ranks.add(rank);
					// save log
					KeywordRealtimeRankSyncLog syncLog = new KeywordRealtimeRankSyncLog();
					syncLog.from(adgroupID, rank.getKeywordID(), new Date(), time);
					KeywordRealtimeRankSyncLog.KeywordRankItem item = new KeywordRealtimeRankSyncLog.KeywordRankItem();
					item.setKeywordID(rank.getKeywordID());
					item.setRank(rank);
					syncLog.setItem(item);
					syncLogs.add(syncLog);
				}
			}
		}

		this.KeywordRealtimeRankSyncLogRepository.save(syncLogs);// save log
		if (ranks != null) {
			for (RankClient.KeywordRealtimeRankItem item : ranks) {
				KeywordRealtimeRank rank = new KeywordRealtimeRank();
				rank.setKeywordID(item.getKeywordID());
				Keyword kw = this.filterKeyword(keywords, item.getKeywordID());
				if (kw != null) {
					rank.setWord(kw.getWord());
				}
				MobileRank mRank = MobileRank.from(item.getMoibleRank());
				PCRank pcRank = PCRank.from(item.getPcRank());
				this.from(rank, device, mRank, pcRank);
				dtos.add(rank);
			}
		}
		return dtos;
	}

	private void from(KeywordRealtimeRank dto, String device, MobileRank mRank, PCRank pcRank) {
		if (DEVICE_MOBILE.equals(device)) {// mobile
			dto.setRank(mRank.getValue());
			dto.setRankName(mRank.name());
			dto.setWirelessRank(mRank.getValue());
			dto.setWirelessRankName(mRank.name());
		} else if (DEVICE_PC.equals(device)) {// pc
			dto.setRank(pcRank.getValue());
			dto.setRankName(pcRank.name());
			dto.setPcRank(pcRank.getValue());
			dto.setPcRankName(pcRank.name());
		} else if (DEVICE_ALL.equals(device)) {// all
			dto.setWirelessRank(mRank.getValue());
			dto.setWirelessRankName(mRank.name());
			dto.setPcRank(pcRank.getValue());
			dto.setPcRankName(pcRank.name());
		}
	}

	private Keyword filterKeyword(List<Keyword> keywords, long keywordID) {
		for (Keyword keyword : keywords) {
			if (keyword.getKeywordId() == keywordID) {
				return keyword;
			}
		}
		return null;
	}
}
